﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using QTPlugin;
using System.IO;
using Kawanon.Usability;

namespace Kawanon.QtHoney
{
	public partial class GestureForm : Form
	{
		private const int D_NORTH = 0;
		private const int D_EAST = 1;
		private const int D_SOUTH = 2;
		private const int D_WEST = 3;

		private List<GestureExpression> m_defaults = new List<GestureExpression>();
		private Dictionary<Action, GestureExpression> m_exprs = new Dictionary<Action, GestureExpression>();
		private IPluginServer m_server;

		class TrailsAlreadyExistsException : ApplicationException
		{
			public GestureExpression Conflict { get; private set; }

			public TrailsAlreadyExistsException(GestureExpression expr)
			{
				Conflict = expr;
			}
		}

		public GestureForm(IPluginServer server)
		{
			InitializeComponent();

			//m_titles.Add(Commands.GoBack, "戻る");
			//m_titles.Add(Commands.GoForward, "進む");
			//m_titles.Add(Commands.GoUpOneLevel, "上へ");
			//m_titles.Add(Commands.RefreshBrowser, "更新");
			//m_titles.Add(Commands.CloseCurrentTab, "閉じる");
			//m_titles.Add(Commands.CloseLeft, "左を閉じる");
			//m_titles.Add(Commands.CloseRight, "右を閉じる");
			//m_titles.Add(Commands.CloseAllButCurrent, "カレント以外を閉じる");
			//m_titles.Add(Commands.CloseAllButOne, "");
			//m_titles.Add(Commands.CloseWindow, "ウィンドウを閉じる");
			//m_titles.Add(Commands.UndoClose, "");
			//m_titles.Add(Commands.BrowseFolder, "");
			//m_titles.Add(Commands.ToggleTopMost, "");
			//m_titles.Add(Commands.FocusFileList, "");
			//m_titles.Add(Commands.OpenTabBarOptionDialog, "");
			//m_titles.Add(Commands.OpenButtonBarOptionDialog, "");
			//m_titles.Add(Commands.IsFolderTreeVisible, "");
			//m_titles.Add(Commands.IsButtonBarVisible, "");
			//m_titles.Add(Commands.ShowFolderTree, "");
			//m_titles.Add(Commands.ShowButtonBar, "");
			//m_titles.Add(Commands.MD5, "");
			//m_titles.Add(Commands.ShowProperties, "");
			//m_titles.Add(Commands.SetModalState, "");
			//m_titles.Add(Commands.SetSearchBoxStr, "");
			//m_titles.Add(Commands.ReorderTabsByName, "");
			//m_titles.Add(Commands.ReorderTabsByPath, "");
			//m_titles.Add(Commands.ReorderTabsByActv, "");
			//m_titles.Add(Commands.ReorderTabsRevers, "");

			m_server = server;

			pictureBox1.Image = new Bitmap(SystemIcons.Information.ToBitmap(), pictureBox1.Size);
		}

		private void ChangeExpression(ListViewItem item, GestureExpression expr, bool userEdit)
		{
			if (userEdit)
			{
				if (!expr.TrailsEquals(GestureExpression.EmptyTrails))
				{
					IList<GestureExpression> list = GestureSettings.OverrideExpressions(m_defaults, m_exprs.Values);
					GestureExpression conflict = GestureSettings.FindExpression(list, expr.Trails);
					if (conflict != null && conflict.Action != expr.Action)
					{
						throw new TrailsAlreadyExistsException(conflict);
					}
				}
			}
			GestureExpression defaultExpr = GestureSettings.FindExpression(m_defaults, expr.Action);
			GestureExpression oldExpr = null;
			m_exprs.TryGetValue(expr.Action, out oldExpr);
			string urdl = expr.FormatTrails();

			if (!defaultExpr.TrailsEquals(expr))
			{
				item.ForeColor = Color.Blue;
				//item.Checked = true;	// ここで与える値はなんでも良い

				//if (userEdit)
				//{
					m_exprs.Remove(expr.Action);
					m_exprs.Add(expr.Action, expr);
				//}
			}
			else
			{
				item.ForeColor = (urdl == String.Empty) ? Color.Gray : Color.Black;
				//item.Checked = false;

				//if (userEdit && oldExpr != null)
				//{
					m_exprs.Remove(expr.Action);
				//}
			}
			item.Text = urdl;
			item.Tag = expr;
		}

		private void UpdateItems(IEnumerable<GestureExpression> list)
		{
			listView1.Items.Clear();
			listView1.SuspendLayout();

			foreach (GestureExpression expr in list)
			{
				ListViewItem item = new ListViewItem(new string[] { String.Empty, expr.Name });
				item.Tag = expr;
				listView1.Items.Add(item);
				ChangeExpression(item, expr, false);
			}

			listView1.ResumeLayout();
		}

		private void GestureForm_Load(object sender, EventArgs e)
		{
			// デフォルト定義（ユーザーが更新した定義は別コレクションに保存）
			m_defaults.AddRange(GestureSettings.GetDefaultExpressions());

			List<GestureExpression> src = new List<GestureExpression>();
			//if (File.Exists(Path.Combine(Application.StartupPath, "hoge.bin")))
			//{
			//    Stream istream = new FileStream(Path.Combine(Application.StartupPath, "hoge.bin"), FileMode.Open);
			//    GestureSettings.LoadExpressions(src);
			//    istream.Close();
			//}
			GestureSettings.LoadExpressions(src);

			IList<GestureExpression> list = GestureSettings.OverrideExpressions(m_defaults, src);
			UpdateItems(list);
		}

		private void GestureForm_FormClosed(object sender, FormClosedEventArgs e)
		{
			//List<GestureExpression> src = new List<GestureExpression>();
			////if (File.Exists(Path.Combine(Application.StartupPath, "hoge.bin")))
			////{
			////    Stream istream = new FileStream(Path.Combine(Application.StartupPath, "hoge.bin"), FileMode.Open);
			////    GestureSettings.LoadExpressions(src);
			////    istream.Close();
			////}
			//GestureSettings.LoadExpressions(src);

			//IList<GestureExpression> list = GestureSettings.OverrideExpressions(src, m_exprs.Values);

			////Stream ostream = new FileStream(Path.Combine(Application.StartupPath, "hoge.bin"), FileMode.Create);
			//GestureSettings.SaveExpressions(list);
			////ostream.Close();

			GestureSettings.SaveExpressions(m_exprs.Values);
		}

		delegate GestureExpression EditExpressionDelegate(GestureExpression oldExpr);

		private void EditExpression(EditExpressionDelegate func)
		{
			ListViewItem item = listView1.FocusedItem;
			if (item == null)
			{
				return;
			}
			GestureExpression oldExpr = (GestureExpression)item.Tag;
			GestureExpression newExpr = func.Invoke(oldExpr);
			if (newExpr == null)
			{
				return;
			}
			try
			{
				ChangeExpression(item, newExpr, true);
			}
			catch (TrailsAlreadyExistsException ex)
			{
				//TODO: 置き換えますか？の実装
				string text = String.Format(
					"{0} は「{1}」として既に登録されています。\r\n「{1}」を無効にして「{2}」を新しく登録しますか？",
					newExpr.FormatTrails(), ex.Conflict.Name, newExpr.Name);
				DialogResult res = MessageBox.Show(this, text, "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
				if (res == DialogResult.Yes)
				{
					List<GestureExpression> src = new List<GestureExpression>(m_exprs.Values);
					src.Remove(ex.Conflict);
					src.Add(new GestureExpression(GestureExpression.EmptyTrails, ex.Conflict.Action));
					src.Remove(oldExpr);
					src.Add(newExpr);
					IList<GestureExpression> list = GestureSettings.OverrideExpressions(m_defaults, src);
					UpdateItems(list);
				}
			}
		}

		private void EditDialog()
		{
			EditExpression(delegate(GestureExpression oldExpr)
			{
				GestureEditForm form = new GestureEditForm();
				form.Expression = oldExpr;

				if (Utility.DoModal(m_server, form) != DialogResult.OK)
				{
					return null;
				}
				
				GestureExpression expr = new GestureExpression(form.Expression.Trails, oldExpr.Action);
				return expr;
			});
		}

		private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			EditDialog();
		}

		private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
		{
			if (e.Label == null)
			{
				return;
			}
			ListViewItem item = listView1.Items[e.Item];
			GestureExpression expr = (GestureExpression)item.Tag;

			string str = e.Label.ToUpper();
			str.Replace('↑', 'U');
			str.Replace('→', 'R');
			str.Replace('↓', 'D');
			str.Replace('←', 'L');
			try
			{
				GestureExpression newExpr = new GestureExpression(str, expr.Action);
				ChangeExpression(item, newExpr, true);
				e.CancelEdit = true;
			}
			catch (FormatException)
			{
				e.CancelEdit = true;
				//TODO: バルーンを出す
			}
		}

		private void listView1_ItemCheck(object sender, ItemCheckEventArgs e)
		{
			//ListViewHitTestInfo hi = listView1.HitTest(listView1.PointToClient(Cursor.Position));
			//if (hi.Item != null && hi.Location != ListViewHitTestLocations.StateImage)
			//{
			//    // ダブルクリックではチェック状態を変化させない
			//    e.NewValue = hi.Item.Checked ? CheckState.Checked : CheckState.Unchecked;
			//}

			//常にチェックを許可しない
			ListViewItem item = listView1.Items[e.Index];
			e.NewValue = (item.ForeColor == Color.Blue) ? CheckState.Checked : CheckState.Unchecked;
		}

		private void ToolStripMenuItem_Edit_Click(object sender, EventArgs e)
		{
			EditDialog();
		}

		private void ToolStripMenuItem_Reset_Click(object sender, EventArgs e)
		{
			EditExpression(delegate(GestureExpression oldExpr)
			{
				GestureExpression defaultExpr = GestureSettings.FindExpression(m_defaults, oldExpr.Action);
				if (defaultExpr == null)
				{
					Dbg.Abort("defaultExpr == null");
				}
				GestureExpression expr = new GestureExpression(defaultExpr.Trails, oldExpr.Action);
				return expr;
			});
		}

		private void ToolStripMenuItem_Clear_Click(object sender, EventArgs e)
		{
			EditExpression(delegate(GestureExpression expr)
			{
				expr.Trails = GestureExpression.EmptyTrails;
				return expr;
			});
		}


	}
}
